<?php

/**
 * Clase logger del frame, registra mensajes del sistema en archivos logs
 *
 * @author Robert Babilonia <bobbabilon2@gmail.com>
 */
final class CommanderLogger {

    /**
     * @var string Indica la ruta del directorio de archivos logs, viene predefinida en el core.php
     * con la constante LOGS_PATH 
     */
    private static $path = LOGS_PATH;

    /**
     * @var pointer Es el puntero al archivo log cuando este ha sido abierto para escritura 
     */
    private static $file_pointer = NULL;

    /**
     * @var array Arreglo asociativo con los tipos de mensajes soportados por la clase logger
     */
    private static $tipo = array('NOTICE' => '[NOTICE]', 'WARNING' => '[WARNING]',
        'ERROR' => '[ERROR]', 'FATAL' => '[FATAL]');

    /**
     * Registra un mensaje con el tipo especificado y en el archivo log indicado, 
     * si el archivo no se indica se crea uno por defecto con la fecha actual
     * @param string $message Cadena con el mensaje a registrar
     * @param strting $messageType Tipo de mensaje a crear, los soportados: NOTICE, WARNING, ERROR, FATAL
     * @param string $logfile Nombre del archivo log a crear,si no se especifica crea un archivo con la fecha actual
     * @throws CommanderException
     */
    public static function log($message, $messageType = 'WARNING', $logfile = NULL) {

        // se verifica que el mensaje recibido sea una cadena de caracteres
        if (!is_string($message)) {

            throw new CommanderException(ERROR_BAD_MESSAGE_TYPE);
        }

        // SE VERIFICA QUE EL TIPO RECIBIDO EXISTA EN LOS PERMITIDOS
        if (!array_key_exists($messageType, self::$tipo)) {

            throw new CommanderException(ERROR_BAD_LOG_TYPE);
        }
        //se obtiene la ruta absoluta del achivo a regstrar
        $file_path = self::get_log_path($logfile);
        self::open_log($file_path);
        self::write_log("[" . date(DATE_LONG_FORMAT) . "]" . self::$tipo[$messageType] . " - " . $message);
        self::close_log();
    }

    /**
     * Obtiene la ruta absoluta del archivo log a construir, baado en la 
     * configuracion y el nombre especificado, si el nombre no se especifica retorna
     * la ruta para un log con la fecha actual
     * @param string $logfile
     * @return string path
     */
    private static function get_log_path($logfile = NULL) {


        if (is_null($logfile)) {

            $logfile = date('Y_m_d') . '.log';
        } else {

            $logfile = $logfile . '.log';
        }

        return self::$path . $logfile;
    }

    /**
     * Abre el archivo log especificado en modo "append" es decir, 
     * si no existe lo crea y si existe lo abre para empezar a escribir al final
     * @param string $logfile
     * @throws CommanderException
     */
    public static function open_log($logfile) {

        self::close_log();

        self::$file_pointer = @fopen($logfile, "a");

        if (!self::$file_pointer) {
            throw new CommanderException(ERROR_OPENING_FILE . $logfile);
        }
    }

    /**
     * Guarda el mensaje especificado en un archivo log previamente abierto
     * @param string $message Mensaje a guardar en el archivo log
     * @throws CommanderException
     */
    private static function write_log($message) {

        if (self::$file_pointer != NULL) {

            flock(self::$file_pointer, LOCK_EX);
            fwrite(self::$file_pointer, $message . "\n");
            flock(self::$file_pointer, LOCK_UN);
        } else {

            throw new CommanderException(ERROR_LOGGER_NOT_OPEN);
        }
    }

    /**
     * Cierra un archivo log previamente abierto
     */
    private static function close_log() {
        if (self::$file_pointer != NULL) {
            fclose(self::$file_pointer);
            self::$file_pointer = NULL;
        }
    }

    /**
     * Registra un salto de linea y separacion en el archivo log registrado
     * @param string $logfile Achivo log a esribir
     */
    public static function jump_log($logfile = NULL) {

        $file_path = self::get_log_path($logfile);
        self::open_log($file_path);
        self::write_log(PHP_EOL . "___________________________________________");
        self::close_log();
    }

    /**
     * Registra un mensaje de tipo NOTICE en un archivo log
     * @param string $message Mensaje a registrar
     * @param string $logfile Archivo log a escribir
     */
    public static function notice_log($message = '', $logfile = NULL) {

        self::log($message, "NOTICE", $logfile);
    }

    /**
     * Registra un mensaje de tipo WARNING o alerta en un archivo log
     * @param string $message Mensaje a registrar
     * @param string $logfile Archivo log a escribir
     */
    public static function warning_log($message = '', $logfile = NULL) {

        self::log($message, "WARNING", $logfile);
    }

    /**
     * Registra un mensaje de tipo ERROR en un archivo log
     * @param string $message Mensaje a registrar
     * @param string $logfile Archivo log a escribir
     */
    public static function error_log($message = '', $logfile = NULL) {

        self::log($message, "ERROR", $logfile);
    }

    /**
     * Registra un mensaje de tipo ERROR FATAL en un archivo log
     * @param string $message Mensaje a registrar
     * @param string $logfile Archivo log a escribir
     */
    public static function fatal_log($message = '', $logfile = NULL) {

        self::log($message, "FATAL", $logfile);
    }

}

?>